package com.sky.rabc.Interceptor;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sky.rabc.common.RedissonCommon;
import com.sky.rabc.common.ThreadLocalCommon;
import com.sky.rabc.enums.ServiceCode;
import com.sky.rabc.exception.ServiceException;
import com.sky.rabc.utils.AesCommon;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;
import java.util.Optional;

@Slf4j
@Repository
public class TokenInterceptor implements HandlerInterceptor {
    @Value("${rabc.aes.key}")
    private String aesKey;
    @Value("${rabc.aes.iv}")
    private String aesIv;

    private final ObjectMapper objectMapper;
    private final RedissonCommon redissonCommon;

    public TokenInterceptor(ObjectMapper objectMapper, RedissonCommon redissonCommon) {
        this.objectMapper = objectMapper;
        this.redissonCommon = redissonCommon;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String token = request.getHeader("token");
        Optional.ofNullable(token).orElseThrow(() -> {
            log.error("请求头:token值为nil,用户token不存在");
            return new ServiceException(ServiceCode.ERROR_TOKEN, "请登录");
        });
        //解密token, 解密后的信息是基于map的json
        String content = AesCommon.decryptToStr(token, aesKey, aesIv, AesCommon.AES_CBC_PKCS5);
        //TypeReference 通过创建一个TypeReference实例并传给Jackson的反序列化方法，可以显式地指定目标复杂类型的泛型信息，从而让Jackson正确地反序列化JSON到期望的复杂类型。
        Map<String, Object> loginInfoMap = objectMapper.readValue(content, new TypeReference<Map<String, Object>>() {
        });
        String userId = loginInfoMap.get("userId").toString();
        String key = "token:userId:" + userId;
        Optional.ofNullable(redissonCommon.getValue(key)).orElseThrow(() -> {
            log.error("缓存token不存在,key:{}", key);
            return new ServiceException(ServiceCode.ERROR_TOKEN, "请登录");
        });
        ThreadLocalCommon.setValue(Long.valueOf(userId));
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalCommon.remove();
        log.debug("处理完成");
    }
}
